package spectra.ee.web.kb.service;

import java.io.UnsupportedEncodingException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import spectra.base.ajax.TransAjax;
import spectra.base.log.Logger;
import spectra.base.util.DateUtil;
import spectra.base.util.StringUtil;
import spectra.base.util.Util;
import spectra.base.web.WebUtil;
import spectra.ee.EEPublic;
import spectra.ee.commons.search.model.form.SearchKbForm;
import spectra.ee.web.WebConfig;
import spectra.ee.web.api.ApiPublic;
import spectra.ee.web.kb.model.Kb;
import spectra.ee.web.kb.model.TopKeyword;

/**
 * KbManager클래스. kbService 에 있는 기능들을 ajax 로 사용하기 위해 제한된 파라메터 객체를 제공하는 함수로 재정의
 * 
 * @author dhheo
 */
public class KbWebService extends KbServiceBase
{

	/** Logger객체. */
	private static Logger logger = Logger.getLoggerInstance(KbManager.class.getName());

	// TODO : 웹정형화 커스터마이징 코드 추가

	/**
	 * <pre>
	 * TOPN FAQ가져오는 메소드
	 * FAQ_KB_TOPN_SYSTEM_TYPE 환경설정에 있는값을 가져와서 시스템정의(TYSYS), 사용자정의(TYUSR)에 따른 TOP-N FAQ를 가져온다.
	 * iCount개수만큼 리스트를 가져온다.
	 * </pre>
	 * 
	 * @param
	 * @return List TopN Faq목록
	 */
	public List selectTopnFaq(Kb kb)
	{
		List list = null;
		try
		{
			String strTopNType = WebConfig.getEnvValue("FAQ_KB_TOPN_SYSTEM_TYPE");
			int iRowCount = Util.str2i(WebConfig.getEnvValue("FAQ_KB_TOPN_COUNT"), 5);

			kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
			kb.setTopnType(strTopNType);
			kb.setEndNo(iRowCount);
			list = (List) sqlMap.queryForList("Kb.selectTopnFaq", kb);
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		}
		return list;
	}

	/**
	 * <pre>
	 * 새로 등록된 FAQ를 가져오는 메소드
	 * </pre>
	 * 
	 * @param
	 * @return List 새로등록된 FAQ목록.
	 */
	public List selectNewFaq(Kb kb)
	{
		List listRet = null;
		try
		{
			kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
			listRet = (List) sqlMap.queryForList("Kb.selectNewFaq", kb);
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		}
		return listRet;
	}

	/**
	 * <pre>
	 * 해당 카테고리에 속하는 FAQ 리스트의 개수를 가져오는 메소드
	 * </pre>
	 * 
	 * @param
	 * @return 해당 카테고리에 속하는 FAQ 리스트의 개수.
	 * @throws Exception the exception.
	 */
	public int selectFaqListCount(Kb kb) throws Exception
	{
		kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
		return ((Integer) sqlMap.queryForObject("Kb.selectFaqListCount", kb))
				.intValue();
	}

	/**
	 * <pre>
	 * 해당 카테고리에 속하는 FAQ 리스트를 가져오는 메소드
	 * </pre>
	 * 
	 * @param
	 * @return List 해당 카테고리에 속하는 FAQ 리스트.
	 */
	public List selectFaqList(Kb kb)
	{
		List listRet = null;
		
		try
		{			
			//정렬 정보가 안넘어오는 경우 설정값으로 초기값을 셋팅한다.
			kb.setOrderBy(StringUtil.defaultIfEmpty(kb.getOrderBy(), WebConfig.getEnvValue("FAQ_PAGE_SORT_TYPE")));
			kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
			listRet = (List) sqlMap.queryForList("Kb.selectFaqList", kb);
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		}
		return listRet;
	}

	/**
	 * <pre>
	 * TOP키워드를 가져오는 메소드이다.
	 * 필수 파라메터값 
	 *  - domainId (도메인 아이디)
	 * </pre>
	 * 
	 * @return List TOP키워드 리스트.
	 */
	public List selectTopKeyword(TopKeyword topKeyword)
	{
		List list = null;
		topKeyword.setServiceType(ApiPublic.SERVICE_TYPE_FAQ);
		topKeyword.setSystemType(WebConfig.getEnvValue("FAQ_KEYWORD_TOPN_SYSTEM_TYPE"));
		topKeyword.setEndNo(Util.str2i(StringUtil.defaultString(WebConfig.getEnvValue("FAQ_KEYWORD_TOPN_COUNT"), "5"), 5));
		
		try
		{
			list = (List) sqlMap.queryForList("TopKeyword.selectTopKeywordListByDomainId", topKeyword);
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		}
		return list;
	}

	/**
	 * 지식ID로 FAQ의 이전글, 다음글 가져오는 메소드.
	 * 
	 * @param
	 * @return List FAQ이전/다음 리스트.
	 */
	public List selectKbPrevNext(Kb kb)
	{
		List listRet = null;

		kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
		try
		{
			listRet = (List) sqlMap.queryForList("Kb.selectKbPrevNext", kb);
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		}
		return listRet;
	}

	/**
	 * 지식ID로 FAQ의 조회 Log를 만드는 메소드.
	 * 
	 * @param logId			로그ID.
	 * @param kbId			지식ID.
	 * @param serviceType	서비스타입.
	 * @param nodeId		노드ID.
	 * @return boolean		성공시 true, 실패시 false
	 */
	public boolean insertKbViewLog(Kb kb)
	{
		boolean result = false;
		int iResult = -1;
		kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());

		try
		{
			sqlMap.startTransaction();
			iResult = sqlMap.update("Kb.insertKbViewLog", kb);
			sqlMap.commitTransaction();
			if (iResult > 0)
			{
				result = true;
			}
		} 
		catch (SQLException e)
		{
			logger.error(e.getMessage());
		} 
		finally
		{
			try
			{
				sqlMap.endTransaction();
			}
			catch (SQLException e)
			{
				logger.error(e.getMessage());
			}
		}
		return result;
	}
	
	/**
    * 지식ID로 FAQ의 상세 내용 가져오는 메소드.
    * 뷰로그를 남기로 조회수를 업데이트 한다.
    * 
    * @param kb 지식.
    * @return List 지식ID로 가져온 내용 리스트. 
    */
    public List selectContentsByKbId(Kb kb)
    {
        List list = null;
        int iResult = -1;
        //log_id, kb_id, service_type, node_id, feedback, created_date
        kb.setLogId(StringUtil.defaultIfEmpty(kb.getLogId(), Util.getGuid()));
        kb.setCurrentDate(DateUtil.getCurrDateTimeStamp());
        
        try
        {
        	sqlMap.startTransaction();
        	iResult = sqlMap.update("Kb.updateKbHitCount", kb.getKbId());
        	if (iResult <= 0)
        	{
        		logger.error("Hit count update fail! :" + iResult);
        	}
        	iResult = -1;
        	iResult = sqlMap.update("Kb.insertKbViewLog", kb);
        	if (iResult <= 0)
        	{
        		logger.error("kb view log update fail! :" + iResult);
        	}
			sqlMap.commitTransaction();            
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
        }
        finally
        {
            try
            {
                sqlMap.endTransaction();
            }
            catch(SQLException e)
            {
                logger.error(e.getMessage());
            }
        }
        //로그 업데이트 실패해도 일단 리스트는 가져오도록 한다.
        try
        {
        	list = (List) sqlMap.queryForList("Kb.selectContentsWithInfoByKbId", kb);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
        }
        return list;
    }

    /**
     * 검색 관련 함수
     * 
     * @return Object 검색결과 
     */
	public Object searchKb(SearchKbForm searchKbForm)
	{
		String strQuestion = searchKbForm.getQuestion();
		try
		{
			strQuestion = java.net.URLEncoder.encode(strQuestion, "UTF-8");
		}
		catch (Exception e) {}

		String strUrl =  WebConfig.getConfigValue("COMMON", "URL_WEBAPPS") + "/search/searchKb.ex";

		strUrl += "?command=searchKbForApi";
		strUrl += "&searchRange=" + searchKbForm.getSearchRange();
		strUrl += "&searchReturnType=" + searchKbForm.getSearchReturnType();
		strUrl += "&returnType=" + TransAjax.RETURN_TYPE_AJAX_JSON_PLAIN;    
		strUrl += "&domainId=" + searchKbForm.getDomainId();
		if (StringUtil.isNotBlank(searchKbForm.getNodeId()))
			strUrl += "&nodeId=" + searchKbForm.getNodeId();
		strUrl += "&serviceType=" + searchKbForm.getServiceType();
		strUrl += "&isSearchLog=" + searchKbForm.getIsSearchLog();
		strUrl += "&isKeywordLog=" + searchKbForm.getIsKeywordLog();
		strUrl += "&isSearchHitCount=" + searchKbForm.getIsSearchHitCount();
		strUrl += "&searchResultCount=" + searchKbForm.getSearchResultCount();
		strUrl += "&volume=" + searchKbForm.getVolume();
		strUrl += "&flag=" + searchKbForm.getFlag();
		strUrl += "&question=" + strQuestion;
		strUrl += "&pageNo=" + searchKbForm.getPageNo();
		strUrl += "&rowsPerPage=" + searchKbForm.getRowsPerPage();
		strUrl += "&langFlag=" + searchKbForm.getLangFlag();
		strUrl += "&searchLogId=" + searchKbForm.getSearchLogId();

		if (searchKbForm.getNodeIdPath().length() > 0)
		{
			strUrl += "&nodeIdPath=" + searchKbForm.getNodeIdPath();
		}

		if ("".equals(strQuestion))
			return "";

		String strResult = WebUtil.getResponseContent(strUrl, "POST");
		
		try
		{
			strResult = java.net.URLDecoder.decode(strResult, "UTF-8");
		} 
		catch (UnsupportedEncodingException ue)
		{
			logger.error(ue.getMessage());
			logger.error("url : " + strUrl);
			logger.error("result : " + strResult);
		}
		catch (Exception e)
		{
			logger.error(e.getMessage());
			logger.error("url : " + strUrl);
			logger.error("result : " + strResult);
		}
		
		JSONObject json = new JSONObject();
		TransAjax transAjax = null;
		Hashtable htSearchRet = null;
		if(strResult != null && !"".equals(strResult))
		{
			transAjax = TransAjax.reverseTransform(strResult, TransAjax.RETURN_TYPE_AJAX_JSON);
			htSearchRet = transAjax.get();
			
			if(EEPublic.FORM_RETURN_SUCCESS.equals((String)htSearchRet.get("RESULT")))
			{
				json = JSONObject.fromObject(strResult);
				JSONArray jsonArray = json.getJSONArray("LIST");
				if(jsonArray != null)
				{
					ArrayList arrList = convertSearchListToObject(jsonArray);
					json.remove("LIST");
					json.put("LIST", arrList);
				}
			}
		}
		
		return json;
	}
	
	private ArrayList convertSearchListToObject(JSONArray jsonArray)
	{
		String[] keys = new String[]{
				"kb_id", "service_type", "node_id", "title", "contents", "tag_list", "node_id_path", 
				"node_path", "attach_count", "created_by", "created_name", "created_date", 
				"updated_by", "updated_name", "updated_date", "hit_count"
				};
		int i = 0;
		ArrayList arrList = new ArrayList();
		Map map = new HashMap();
		for (Iterator it = jsonArray.iterator(); it.hasNext();)
		{
			map.put(keys[i++], it.next());
			if (i >= keys.length)
			{
				arrList.add(map);
				map = new HashMap();
				i = 0;
			}
		}
		
		return arrList;
	}
}
